package it.traveldream.beans;

import it.traveldream.dto.UserDTO;
import it.traveldream.entities.Customer;
import it.traveldream.entities.CustomerInvites;
import it.traveldream.entities.UserType;
import it.traveldream.exceptions.InvalidCredentialsException;
import it.traveldream.utils.DefaultValidator;
import it.traveldream.utils.Validator;

import java.util.logging.Logger;

import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;

/**
 * Session Bean implementation class AccountManager
 */
@Stateless
public class AccountManager implements AccountFactoryInterface {

	private Validator validator;
	private Logger log;
	@PersistenceContext
	private EntityManager em;
	
	@Resource
	private EJBContext context;
	
    /**
     * Default constructor. 
     */
    public AccountManager() {
        super();
        this.log = Logger.getLogger(this.getClass().getSimpleName());
    }

    public void setValidator(Validator validator){
    	this.validator = validator;
    }
    
	@Override
	public boolean validateCredentials(UserDTO user, Validator validator) {
		if (user == null || validator == null)
			throw new IllegalArgumentException();
		
		if (user.getUsername().equals(""))
			return validator.validateCredentials(user.getEmail(), user.getPassword());
		
		return validator.validateCredentials(user.getUsername(), user.getEmail(), user.getPassword());
	}

	@Override
	public void saveCustomer(UserDTO user) throws InvalidCredentialsException {
		try{
			if (user == null) throw new IllegalArgumentException();
			
			if (this.validator == null)
				this.validator = new DefaultValidator();
			boolean validCredentials = false;
			
			if (user.getUsername().equals(""))
				validCredentials = this.validator.validateCredentials(user.getEmail(), user.getPassword());
			else
				validCredentials = this.validator.validateCredentials(user.getUsername(), user.getEmail(), user.getPassword());
			
			if (! validCredentials)
				throw new InvalidCredentialsException();
			
			Customer customer = new Customer(user);
			UserType c = this.em.find(UserType.class, "Customer");
			c.getUsers().add(customer);
			c.setUsers(c.getUsers());
			customer.setDiscountPercentage(0);
			
			if (user.getInvitationLink() != null){
				CustomerInvites invite = (CustomerInvites) this.em.createNamedQuery("getInvitesByLink").
						setParameter("link", user.getInvitationLink()).getSingleResult();
				if (invite != null){
					customer.setDiscountPercentage(Customer.BASIC_DISCOUNT_VALUE);
					
					Customer original = invite.getCustomer();
					original.setDiscountPercentage(Customer.BASIC_DISCOUNT_VALUE);
					this.em.merge(original);
				}
			}
			
			this.em.persist(customer);
			this.em.flush();
		} catch (PersistenceException e){
			this.log.severe("ERROR: Saving customer " + e.getMessage());
			throw new InvalidCredentialsException();
		} catch (RuntimeException e){
			this.log.severe("ERROR: Saving customer " + e.getMessage());
			throw new RuntimeException();
		}
	}

	@Override
	@RolesAllowed(Customer.role)
	public UserDTO getCurrentCustomer() {
		String username = this.context.getCallerPrincipal().getName();
		Customer user = this.em.find(Customer.class, username);
		if (user == null)
			return null;
		this.em.refresh(user);
		return user.toDTO();
	}
}
